package cn.getech.data.metadata.service.impl;

import cn.getech.data.intelligence.common.utils.DateUtils;
import cn.getech.data.intelligence.common.utils.NameValue;
import cn.getech.data.metadata.controller.module.ModuleUtils;
import cn.getech.data.metadata.entity.CollectionSystemModuleEntity;
import cn.getech.data.metadata.entity.CollectionSystemStorageDayEntity;
import cn.getech.data.metadata.entity.meta.CollectionTableInfo;
import cn.getech.data.metadata.mapper.CollectionTableStatisticsMapper;
import cn.getech.data.metadata.model.res.collectiontablestatistics.SystemStorageDayInner;
import cn.getech.data.metadata.model.res.collectiontablestatistics.SystemStorageDayRes;
import cn.getech.data.metadata.model.res.collectiontablestatistics.TableHotRes;
import cn.getech.data.metadata.model.res.collectiontablestatistics.TableStatisticsRes;
import cn.getech.data.metadata.service.CollectionSystemModuleService;
import cn.getech.data.metadata.service.CollectionSystemStorageDayService;
import cn.getech.data.metadata.service.CollectionTableInfoService;
import cn.getech.data.metadata.service.CollectionTableStatisticsService;
import cn.getech.system.center.utils.ShiroUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class CollectionTableStatisticsServiceImpl implements CollectionTableStatisticsService {
    @Autowired
    private CollectionTableStatisticsMapper collectionTableStatisticsMapper;
    @Autowired
    private CollectionSystemModuleService collectionSystemModuleService;
    @Autowired
    private CollectionTableInfoService collectionTableInfoService;
    @Autowired
    private CollectionSystemStorageDayService collectionSystemStorageDayService;

    @Override
    public TableStatisticsRes tableStatistics() {
        Integer tenantId = ShiroUtils.getTenantId();
        return collectionTableStatisticsMapper.tableStatistics(tenantId);
    }

    @Override
    public SystemStorageDayRes systemStorageDay30() {
        Date endTime = DateUtils.getDayEndTime(new Date());
        Date beginTime = DateUtils.getDayStartTime(DateUtils.addDateDays(endTime, -29));
        List<String> times = new ArrayList<>();
        Date curr = beginTime;
        while (curr.getTime() < endTime.getTime()) {
            times.add(DateUtils.format(curr, "MM-dd"));
            curr = DateUtils.addDateDays(curr, 1);
        }
        Integer tenantId = ShiroUtils.getTenantId();
        Map<String, Object> params = new HashMap<>();
        params.put("beginTime", beginTime);
        params.put("endTime", endTime);
        params.put("tenantId", tenantId);
        List<SystemStorageDayInner> dataList = collectionTableStatisticsMapper.systemStorageDay30(params);
        List<CollectionSystemModuleEntity> moduleList = collectionSystemModuleService.list(new QueryWrapper<CollectionSystemModuleEntity>()
                .eq(tenantId != null, "tenant_id", tenantId).or()
                .eq("sm_id",-1));
        Map<Integer, String> systemMap = wrapData(dataList, moduleList);
        Map<String, List<NameValue<BigDecimal>>> systemData = new HashMap<>();
        for (int i = 0; i < times.size(); i++) {
            String time = times.get(i);
            for (Integer systemId : systemMap.keySet()) {
                String name = systemMap.get(systemId);
                if (!systemData.containsKey(name)) {
                    List<NameValue<BigDecimal>> values = new ArrayList<>();
                    systemData.put(name, values);
                }
                List<NameValue<BigDecimal>> values = systemData.get(name);
                double sum = dataList.stream().filter(s -> s.getOwnSystem() != null &&
                        s.getOwnSystem().equals(systemId) && s.getModuleSize() > 0 && s.getCreateTime().equals(time)
                ).mapToDouble(SystemStorageDayInner::getModuleSize).sum();
                NameValue<BigDecimal> item = new NameValue<BigDecimal>();
                item.setName(time);
                BigDecimal value = new BigDecimal(sum);
                value = value.divide(new BigDecimal(1024 * 1024 * 1024)).setScale(2, BigDecimal.ROUND_HALF_UP);
                item.setValue(value);
                values.add(item);
            }
        }
        SystemStorageDayRes res = new SystemStorageDayRes();
        res.setTimes(times);
        res.setSystemData(systemData);
        return res;
    }

    @Override
    public List<TableHotRes> tableHot10() {
        Integer tenantId = ShiroUtils.getTenantId();
        return collectionTableStatisticsMapper.tableHot10(tenantId);
    }

    @Override
    public List<Map<String,Object>> systemStorage() {
        Integer tenantId = ShiroUtils.getTenantId();
        List<Map<String,Object>> returnList = new ArrayList<>();
        List<SystemStorageDayInner> dataList = collectionTableStatisticsMapper.systemStorage(tenantId);
        if (CollectionUtils.isEmpty(dataList)) {
            return returnList;
        }
        List<CollectionSystemModuleEntity> moduleList = collectionSystemModuleService.list(new QueryWrapper<CollectionSystemModuleEntity>()
                .eq(tenantId != null, "tenant_id", tenantId).or()
                .eq("sm_id",-1));
        if (CollectionUtils.isEmpty(moduleList)) {
            return returnList;
        }
        Map<Integer, String> systemMap = wrapData(dataList, moduleList);
        for (Integer systemId : systemMap.keySet()) {
            NameValue<BigDecimal> item = new NameValue<>();
            item.setName(systemMap.get(systemId));
            //list.stream().mapToDouble(User::getHeight).sum();
            double sum = dataList.stream().filter(s -> systemId.equals(s.getOwnSystem())
                    && s.getModuleSize() > 0).mapToDouble(SystemStorageDayInner::getModuleSize).sum();
            BigDecimal value = new BigDecimal(sum);
            value = value.divide(new BigDecimal(1024 * 1024 * 1024)).setScale(2, BigDecimal.ROUND_HALF_UP);
//            item.setValue(value);
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("name",systemMap.get(systemId));
            map.put("value",value);
            map.put("id",systemId);
            returnList.add(map);
        }
        return returnList;
    }

    private Map<Integer, String> wrapData(List<SystemStorageDayInner> dataList, List<CollectionSystemModuleEntity> moduleList) {
        Map<Integer, String> systemMap = new HashMap<>();
        for (SystemStorageDayInner systemStorageDayInner : dataList) {
            CollectionSystemModuleEntity root = ModuleUtils.getRootParent(moduleList, systemStorageDayInner.getOwnModule());
            if (root != null) {
                systemStorageDayInner.setOwnSystem(root.getSmId());
                if (systemStorageDayInner.getModuleSize() > 0) {
                    systemMap.put(root.getSmId(), root.getSmName());
                }
            }else{
                log.warn("目录{}不存在根目录,不计入统计中",systemStorageDayInner.getOwnModule());
            }
        }
        return systemMap;
    }

    @Override
    public void generateSystemStorageDay() {
        List<CollectionSystemModuleEntity> moduleList = collectionSystemModuleService.list();
        List<CollectionTableInfo> list = collectionTableInfoService.list(new QueryWrapper<CollectionTableInfo>()
                .eq("delete_flag",0));
        Date now = new Date();
        //每次清理当天的数据
        String pre = DateUtils.format(now, "yyyy-MM-dd");
        Date startDate = DateUtils.stringToDate(pre + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
        Date endDate = DateUtils.stringToDate(pre + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
        collectionSystemStorageDayService.remove(new QueryWrapper<CollectionSystemStorageDayEntity>()
                .ge("create_time", startDate).le("create_time", endDate));
        List<CollectionSystemStorageDayEntity> storageDayList = new ArrayList<>();
        Map<Integer, List<CollectionTableInfo>> moduleListMap = list.stream().filter(s -> s.getOwnModule() != null)
                .collect(Collectors.groupingBy(CollectionTableInfo::getOwnModule));
        for (Integer moduleId : moduleListMap.keySet()) {
            List<CollectionTableInfo> moduleTableList = moduleListMap.get(moduleId);
            Map<Integer, List<CollectionTableInfo>> tenantIdMap = moduleTableList.stream().filter(
                    s -> s.getTenantId() != null)
                    .collect(Collectors.groupingBy(CollectionTableInfo::getTenantId));
            for (Integer tenantId : tenantIdMap.keySet()) {
                List<CollectionTableInfo> tableTenantIdList = tenantIdMap.get(tenantId);
                if (CollectionUtils.isNotEmpty(tableTenantIdList)) {
                    double sum = tableTenantIdList.stream().filter(s ->s.getTotalSize()!=null&&
                            s.getTotalSize() > 0).mapToDouble(CollectionTableInfo::getTotalSize).sum();
                    CollectionSystemStorageDayEntity storageDayEntity = new CollectionSystemStorageDayEntity();
                    storageDayEntity.setTableId(tenantId);
                    storageDayEntity.setTableName(tableTenantIdList.size()+"张表");
                    CollectionSystemModuleEntity root = ModuleUtils.getRootParent(moduleList, moduleId);
                    if (root == null) {
                        continue;
                    }
                    if (sum > 0) {
                        storageDayEntity.setOwnSystem(root.getSmId());
                        storageDayEntity.setOwnModule(moduleId);
                        storageDayEntity.setTotalSize(new BigDecimal(sum));
                        storageDayEntity.setCreateTime(now);
                        storageDayList.add(storageDayEntity);
                    }
                }
            }
        }
        collectionSystemStorageDayService.saveBatch(storageDayList);
    }
}
